// 后端 Mock

import readline from 'readline';
import fs from 'fs';

const VIDEO_MOCK = 'res/videoResultsMock.avi';
const NOTIFICATION_HANDLERS = {
  exit: () => process.exit(0),
};
const REQUEST_HANDLERS = {
  processVideo, // eslint-disable-line no-use-before-define
};

function applyDefaultsSimple(obj, defaults) {
  Object.keys(defaults).forEach((key) => {
    if (!Object.keys(obj).includes(key)) {
      obj[key] = defaults[key];
    }
  });
}

function checkFields(obj, fields, errorGenerator = null) {
  const existingFields = Object.keys(obj);
  fields.forEach((field) => {
    if (!existingFields.includes(field)) {
      if (errorGenerator === null) {
        throw new Error(`缺失 ${field} 字段`);
      } else {
        throw errorGenerator(field);
      }
    }
  });
}

function checkJSONRPC(obj) {
  if (obj.jsonrpc !== '2.0') {
    throw new Error(`无效的 jsonrpc 字段：${obj.jsonrpc}`);
  }
}

function processVideo(params) {
  applyDefaultsSimple(params, {
    resultsDir: '.',
    samplingRate: 400,
    alpha: 15,
    sigma: 3,
    pyrType: 'octave',
    videoScale: 1,
  });
  checkFields(params, [
    'inFile',
    'loCutoff',
    'hiCutoff',
    'resultsDir',
    'samplingRate',
    'alpha',
    'sigma',
    'pyrType',
    'videoScale',
  ]);
  const {
    inFile,
    loCutoff,
    hiCutoff,
    resultsDir,
    samplingRate,
    alpha,
    sigma,
    pyrType,
    videoScale,
  } = params;
  const filename = `${inFile.substring(Math.max(inFile.lastIndexOf('/'), inFile.lastIndexOf('\\')) + 1)}-${loCutoff}-${hiCutoff}-${samplingRate}-${alpha}-${sigma}-${pyrType}-${videoScale}.avi`;
  fs.copyFileSync(VIDEO_MOCK, `${resultsDir}/${filename}`);
  return {
    outFile: filename,
  };
}

function dispatchRequestOrNotification(payload) {
  if (payload.id !== undefined) {
    try {
      checkJSONRPC(payload);
      checkFields(payload, ['method', 'params', 'jsonrpc']);
      checkFields(REQUEST_HANDLERS, [payload.method], field => new Error(`方法不存在：${field}`));
      console.log(JSON.stringify({
        jsonrpc: '2.0',
        id: payload.id,
        result: REQUEST_HANDLERS[payload.method](payload.params),
      }, undefined, 0));
    } catch (error) {
      console.log(JSON.stringify({
        jsonrpc: '2.0',
        id: payload.id,
        error: {
          code: -500,
          message: error.message,
          data: error,
        },
      }, undefined, 0));
    }
  } else {
    checkJSONRPC(payload);
    checkFields(payload, ['method', 'params', 'jsonrpc']);
    checkFields(NOTIFICATION_HANDLERS, [payload.method], field => new Error(`方法不存在：${field}`));
    NOTIFICATION_HANDLERS[payload.method](payload.params);
  }
}

function startServer() {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rl.on('line', (line) => {
    if (line.trim().startsWith('{')) {
      try {
        const payload = JSON.parse(line);
        dispatchRequestOrNotification(payload);
      } catch (error) {
        console.log('出错:', error.message);
      }
    }
  });
}

console.log(`当前使用的是模拟后端（使用 ${VIDEO_MOCK} 作为视频模拟处理结果）`);
startServer();
console.log('后端服务已启动');
